home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / board / Chaos53src.lha / chaos / src / Players.c < prev    next >
C/C++ Source or Header  |  1994-10-14  |  14KB  |  593 lines

  1. /*  Chaos:            The Chess HAppening Organisation System    V5.3
  2.     Copyright (C)   1993    Jochen Wiedmann
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.     $RCSfile: Players.c,v $
  20.     $Revision: 3.2 $
  21.     $Date: 1994/10/14 09:44:02 $
  22.  
  23.     This file contains the functions of the Players-menu.
  24.  
  25.     Computer:    Amiga 1200            Compiler:    Dice 2.07.54 (3.0)
  26.  
  27.     Author:    Jochen Wiedmann
  28.         Am Eisteich 9
  29.       72555 Metzingen
  30.         Phone: 07123 / 14881
  31.         Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
  32. */
  33.  
  34.  
  35. #ifndef CHAOS_H
  36. #include "chaos.h"
  37. #endif
  38. #include <time.h>
  39.  
  40.  
  41.  
  42.  
  43. /*
  44.     InsertPlayer inserts a player into the alphabetically sorted list of
  45.     players.
  46.  
  47.     Inputs: plrlist - pointer to the list, where the player should be
  48.               inserted
  49.         tn        - pointer to the Player structure of the new player
  50. */
  51. static void InsertPlayer (struct List *plrlist, struct Player *tn)
  52.  
  53. { struct Player *node;
  54.  
  55.   for (node = (struct Player *) PlayerList.lh_Head;
  56.        node->Tn_Node.ln_Succ != NULL;
  57.        node = (struct Player *) node->Tn_Node.ln_Succ)
  58.   { if (Stricmp((STRPTR) tn->Name, (STRPTR) node->Name) < 0)
  59.     { break;
  60.     }
  61.   }
  62.   Insert(&PlayerList, (struct Node *) tn, node->Tn_Node.ln_Pred);
  63. }
  64.  
  65.  
  66.  
  67.  
  68. /*
  69.     This function removes preceding blanks from a string.
  70.  
  71.     Inputs: str     - a pointer to the string, where the blanks should
  72.               be removed
  73.  
  74.     Result: a pointer to the first nonblank character in str (may be \0!)
  75. */
  76. static char *WithoutBlanks(char *str)
  77.  
  78. { if (str != NULL)
  79.   { while (*str == ' ')
  80.     { ++str;
  81.     }
  82.   }
  83.   return(str);
  84. }
  85.  
  86.  
  87.  
  88.  
  89. /*
  90.     CheckPlayerValid() checks, if a players data is valid.
  91.  
  92.     Inputs: plr     - a pointer to the player structure
  93.         user    - TRUE, if an error message may be shown to the user
  94.  
  95.     Result: TRUE, if the player is valid, FALSE otherwise
  96.  
  97.     Note: This functions assumes, that plr is not included in PlayerList!
  98. */
  99. int CheckPlayerValid(struct Player *plr, int user)
  100.  
  101. { struct Player *cmpplr;
  102.   char *birthday = WithoutBlanks(plr->BirthDay);
  103.   char *name = WithoutBlanks(plr->Name);
  104.   struct tm tm;
  105.  
  106.  
  107.   /*
  108.       Check if the players name and birthday are valid
  109.   */
  110.   if (*WithoutBlanks(name) == '\0')
  111.   { if (user)
  112.     { ShowError((char *) GetChaosString(MSG_MISSING_PLAYER_NAME));
  113.     }
  114.     return(FALSE);
  115.   }
  116.   if (*birthday != '\0'  &&  !atotm(birthday, &tm))
  117.   { if (user)
  118.     { ShowError((char *) GetChaosString(MSG_BIRTHDAY_ERROR));
  119.     }
  120.     return(FALSE);
  121.   }
  122.  
  123.  
  124.   /*
  125.       Check, if the players name is unique.
  126.   */
  127.   for (cmpplr = (struct Player *) PlayerList.lh_Head;
  128.        cmpplr->Tn_Node.ln_Succ != NULL;
  129.        cmpplr = (struct Player *) cmpplr->Tn_Node.ln_Succ)
  130.   { if (Stricmp((STRPTR) cmpplr->Name, (STRPTR) name) == 0)
  131.     { if (user)
  132.       { ShowError((char *) GetChaosString(MSG_PlayerExists), plr->Name);
  133.       }
  134.       return(FALSE);
  135.     }
  136.   }
  137.   return(TRUE);
  138. }
  139.  
  140.  
  141.  
  142.  
  143.  
  144. /*
  145.     The AddPlayer() function adds a new player to the list of players.
  146.     It is assumed, that CheckPlayer() and CheckPlayerNameUnique() are
  147.     already called.
  148.  
  149.     Inputs: plr     a pointer to a player structure
  150.  
  151.     Results:    TRUE, if successfull, FALSE otherwise
  152. */
  153. int AddPlayer(struct Player *plr)
  154.  
  155. { struct Player *newplr, **plrptr;
  156.   struct Game *game;
  157.  
  158.   /*
  159.       Allocate memory for the new player
  160.   */
  161.   if ((newplr = GetMem(&TrnMem, sizeof(*newplr)))  ==  NULL)
  162.   { return(FALSE);
  163.   }
  164.  
  165.   /*
  166.       Initialize data
  167.   */
  168.   strcpy(newplr->Name, WithoutBlanks(plr->Name));
  169.   strcpy(newplr->Street, WithoutBlanks(plr->Street));
  170.   strcpy(newplr->Village, WithoutBlanks(plr->Village));
  171.   strcpy(newplr->PhoneNr, WithoutBlanks(plr->PhoneNr));
  172.   strcpy(newplr->ChessClub, WithoutBlanks(plr->ChessClub));
  173.   strcpy(newplr->BirthDay, WithoutBlanks(plr->BirthDay));
  174.   strcpy(newplr->DWZ, WithoutBlanks(plr->DWZ));
  175.   newplr->ELO = plr->ELO;
  176.   newplr->Flags = plr->Flags & (TNFLAGSF_SENIOR|TNFLAGSF_JUNIOR|
  177.                 TNFLAGSF_WOMAN|TNFLAGSF_JUNIORA|
  178.                 TNFLAGSF_JUNIORB|TNFLAGSF_JUNIORC|
  179.                 TNFLAGSF_JUNIORD|TNFLAGSF_JUNIORE);
  180.   newplr->Tn_Node.ln_Name = newplr->Name;
  181.   newplr->Tn_Node.ln_Type = (UBYTE) -1;
  182.   newplr->Tn_Node.ln_Pri = 0;
  183.  
  184.   /*
  185.       The Swiss Pairing allows adding players, until round 1 is finished.
  186.       Possibly we have to select an opponent.
  187.   */
  188.   if(NumRounds > 0)
  189.   { /*
  190.     Allocate a Game structure
  191.     */
  192.     if    ((game = newplr->First_Game = GetMem(&TrnMem, sizeof(*game)))
  193.            ==  NULL)
  194.     { PutMem(newplr);
  195.       return(FALSE);
  196.     }
  197.     game->BoardNr = NumPlayers / 2;
  198.  
  199.     /*
  200.     Add the new player to the bottom of the internal rankings.
  201.     */
  202.     for (plrptr = &RankingFirst; *plrptr != NULL;
  203.      plrptr = &((*plrptr)->RankNext))
  204.     {
  205.     }
  206.     *plrptr = newplr;
  207.  
  208.     /*
  209.     If the number of players was odd, the new players opponent will
  210.     be the player, who had a point for free.
  211.     */
  212.     if ((NumPlayers % 2) != 0)
  213.     { struct Player *opponent;
  214.  
  215.       for (opponent = RankingFirst;
  216.        (opponent->Flags & TNFLAGSF_HADFREE) == 0;
  217.        opponent = opponent->RankNext)
  218.       {
  219.       }
  220.  
  221.       opponent->Flags &= ~TNFLAGSF_HADFREE;
  222.       game->Opponent = opponent;
  223.       game->Result = -1;
  224.       game->Flags = (RangeRand(2) == 0)  ?  GMFLAGSF_WHITE : 0;
  225.       newplr->HowMuchWhite = newplr->HowMuchWhiteLast =
  226.                  game->Flags  ?  1 : -1;
  227.  
  228.       game = opponent->First_Game;
  229.       game->Opponent = newplr;
  230.       game->Result = -1;
  231.       game->BoardNr = newplr->First_Game->BoardNr;
  232.       game->Flags = GMFLAGSF_WHITE-newplr->First_Game->Flags;
  233.       opponent->HowMuchWhite = opponent->HowMuchWhiteLast =
  234.                    game->Flags  ? 1 : -1;
  235.       opponent->Points = 0;
  236.       NumGamesMissing++;
  237.     }
  238.     /*
  239.     The new player gets a point for free, if the number of players
  240.     was even.
  241.     */
  242.     else
  243.     { newplr->Flags |= TNFLAGSF_HADFREE;
  244.       newplr->Points = WinnerPoints;
  245.       game->Result = 2;
  246.       game->Flags = GMFLAGSF_POINTFORFREE|GMFLAGSF_NOFIGHT;
  247.     }
  248.   }
  249.  
  250.   InsertPlayer(&PlayerList, newplr);
  251.   NumPlayers++;
  252.  
  253.   IsSaved = FALSE;
  254.   return(TRUE);
  255. }
  256.  
  257.  
  258.  
  259.  
  260. /*
  261.     The AddPlayers() function allows the user to enter new players.
  262. */
  263. void AddPlayers(void)
  264.  
  265. { struct Player plr;
  266.   int new = TRUE;
  267.  
  268.   /*
  269.       Check, if we may enter new players.
  270.   */
  271.   if (NumRounds >= 1 &&  RoundRobinTournament)
  272.   { ShowError((char *) GetChaosString(MSG_NO_NEW_PLAYERS_ROUND_ROBIN));
  273.     return;
  274.   }
  275.   if (NumRounds > 1  &&  SwissPairingTournament)
  276.   { ShowError((char *) GetChaosString(MSG_NO_NEW_PLAYERS_SWISS_PAIR));
  277.     return;
  278.   }
  279.   if (NumRounds > 0)
  280.   { if (!AskContinue((char *) GetChaosString(MSG_NEW_PLAYER_REQUEST)))
  281.     { return;
  282.     }
  283.   }
  284.  
  285.   if (!InitPlrWnd((char *) GetChaosString(WND_PLAYER_ADD_TITLE)))
  286.   { return;
  287.   }
  288.  
  289.   memset(&plr, 0, sizeof(plr));
  290.   for (;;)
  291.   { if (!ProcessPlrWnd(&plr, new))
  292.     { break;
  293.     }
  294.     new = FALSE;
  295.  
  296.     if (CheckPlayerValid(&plr, TRUE))
  297.     { if (!AddPlayer(&plr))
  298.       { break;
  299.       }
  300.  
  301.       memset(&plr, 0, sizeof(plr));
  302.       new = TRUE;
  303.     }
  304.   }
  305.   TerminatePlrWnd();
  306. }
  307.  
  308.  
  309.  
  310.  
  311.  
  312. /*
  313.     The InportPlayers() function allows to add players from a previous
  314.     tournament.
  315. */
  316. void ImportPlayers(void)
  317.  
  318. { void *PlrMem = NULL;
  319.   struct List ImportPlayerList;
  320.  
  321.   /*
  322.       Check, if we may enter new players.
  323.   */
  324.   if (NumRounds >= 1 &&  RoundRobinTournament)
  325.   { ShowError((char *) GetChaosString(MSG_NO_NEW_PLAYERS_ROUND_ROBIN));
  326.     return;
  327.   }
  328.   if (NumRounds > 1  &&  SwissPairingTournament)
  329.   { ShowError((char *) GetChaosString(MSG_NO_NEW_PLAYERS_SWISS_PAIR));
  330.     return;
  331.   }
  332.   if (NumRounds > 0)
  333.   { if (!AskContinue((char *) GetChaosString(MSG_NEW_PLAYER_REQUEST)))
  334.     { return;
  335.     }
  336.   }
  337.  
  338.   if (LoadTournament(NULL, &PlrMem, &ImportPlayerList)  ==  RETURN_OK)
  339.   { if (ProcessPlrSelWnd((char *) GetChaosString(MSG_ImportPlayersWinTitle),
  340.              (char *) GetChaosString(MSG_ImportPlayersOkButton),
  341.              *(char *) GetChaosString(MSG_ImportPlayersOkButtonSC),
  342.              0, &ImportPlayerList))
  343.     { struct Player *plr;
  344.  
  345.       for (plr = (struct Player *) ImportPlayerList.lh_Head;
  346.        plr->Tn_Node.ln_Succ != NULL;
  347.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  348.       { if (plr->Flags & TNFLAGSF_SELECTED)
  349.     { while(!CheckPlayerValid(plr, TRUE))
  350.       { if (!ModifyOnePlayer(plr, TRUE))
  351.         { goto Terminate;
  352.         }
  353.       }
  354.     }
  355.       }
  356.  
  357.       for (plr = (struct Player *) ImportPlayerList.lh_Head;
  358.        plr->Tn_Node.ln_Succ != NULL;
  359.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  360.       {
  361.     if ((plr->Flags & TNFLAGSF_SELECTED)  &&  !AddPlayer(plr))
  362.     { break;
  363.     }
  364.       }
  365.     }
  366.   }
  367.  
  368. Terminate:
  369.   PutMemList(&PlrMem);
  370. }
  371.  
  372.  
  373.  
  374.  
  375.  
  376. /*
  377.     The ModifyPlayer() function modifys one player. This function assumes,
  378.     that CheckPlayer() and CheckPlayerNameUnique() are already called.
  379. */
  380. void ModifyPlayer(struct Player *old, struct Player *new)
  381.  
  382. {
  383.   Remove(&old->Tn_Node);
  384.   memcpy(old, new, sizeof(*old));
  385.   strcpy(old->Name, WithoutBlanks(old->Name));
  386.   strcpy(old->Street, WithoutBlanks(old->Street));
  387.   strcpy(old->Village, WithoutBlanks(old->Village));
  388.   strcpy(old->PhoneNr, WithoutBlanks(old->PhoneNr));
  389.   strcpy(old->ChessClub, WithoutBlanks(old->ChessClub));
  390.   strcpy(old->BirthDay, WithoutBlanks(old->BirthDay));
  391.   strcpy(old->DWZ, WithoutBlanks(old->DWZ));
  392.   InsertPlayer(&PlayerList, old);
  393.   IsSaved = FALSE;
  394. }
  395.  
  396.  
  397.  
  398.  
  399. /*
  400.     ModifyOnePlayer() allows to modify one player.
  401.  
  402.     Inputs: plr     - a pointer to the player structure
  403.         initwin - a flag which indicates, if the player window needs
  404.               to be initialized
  405.  
  406.     Result: TRUE, if successfull, FALSE otherwise
  407. */
  408. int ModifyOnePlayer(struct Player *plr, int initwin)
  409.  
  410. { int result = 0;
  411.  
  412.   if (!initwin  ||
  413.       InitPlrWnd((char *) GetChaosString(WND_PLAYER_MODIFY_TITLE)))
  414.   { int new = TRUE;
  415.     struct Player modifiedplr;
  416.  
  417.     memcpy(&modifiedplr, plr, sizeof(modifiedplr));
  418.     do
  419.     { if (!ProcessPlrWnd(&modifiedplr, new))
  420.       { goto Terminate;
  421.       }
  422.  
  423.  
  424.       Remove((struct Node *) plr);
  425.       result = CheckPlayerValid(&modifiedplr, TRUE);
  426.       Insert((struct List *) &PlayerList, (struct Node *) plr,
  427.          plr->Tn_Node.ln_Pred);
  428.     }
  429.     while (!result);
  430.  
  431.     ModifyPlayer(plr, &modifiedplr);
  432.   }
  433.  
  434. Terminate:
  435.   if (initwin)
  436.   { TerminatePlrWnd();
  437.   }
  438.   return(result);
  439. }
  440.  
  441.  
  442.  
  443.  
  444.  
  445. /*
  446.     ModifyPlayers() is called from the menu to modify player data.
  447. */
  448. void ModifyPlayers(void)
  449.  
  450. {
  451.   /*
  452.       Check, if we really may modify players
  453.   */
  454.   if (NumRounds > 0)
  455.   { if (!AskContinue((char *) GetChaosString(MSG_MODIFY_PLAYER_REQUEST)))
  456.     { return;
  457.     }
  458.   }
  459.  
  460.   if (ProcessPlrSelWnd((char *) GetChaosString(WND_PLAYER_MODSEL_TITLE),
  461.                (char *) GetChaosString(BUTTON_MODIFY_TITLE),
  462.                *(char *) GetChaosString(BUTTON_MODIFY_SC), 0,
  463.                &PlayerList))
  464.   { if (InitPlrWnd((char *) GetChaosString(WND_PLAYER_MODIFY_TITLE)))
  465.     { struct Player *plr;
  466.  
  467.       /*
  468.       Copy the old link pointers, because they may be changed when
  469.       calling ModifyPlayer()!
  470.       */
  471.       for (plr = (struct Player *) PlayerList.lh_Head;
  472.        plr->Tn_Node.ln_Succ != NULL;
  473.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  474.       { if (((struct Player *) plr->Tn_Node.ln_Succ)->Tn_Node.ln_Succ != NULL)
  475.     { plr->Helpptr = (struct Player *) plr->Tn_Node.ln_Succ;
  476.     }
  477.     else
  478.     { plr->Helpptr = NULL;
  479.     }
  480.       }
  481.  
  482.  
  483.       for (plr = (struct Player *) PlayerList.lh_Head;
  484.        plr != NULL;
  485.        plr = plr->Helpptr)
  486.       { if (plr->Flags & TNFLAGSF_SELECTED)
  487.     { if(!ModifyOnePlayer(plr, FALSE))
  488.       { TerminatePlrWnd();
  489.         return;
  490.       }
  491.     }
  492.       }
  493.  
  494.       TerminatePlrWnd();
  495.     }
  496.   }
  497. }
  498.  
  499.  
  500.  
  501.  
  502. /*
  503.     The DeletePlayer() function deletes one player or marks him as
  504.     withdrawn.
  505. */
  506. void DeletePlayer(struct Player *plr)
  507.  
  508. {
  509.   if (NumRounds == 0)
  510.   { Remove(&plr->Tn_Node);
  511.     PutMem(plr);
  512.     NumPlayers--;
  513.   }
  514.   else
  515.   { plr->Flags |= TNFLAGSF_WITHDRAWN;
  516.   }
  517.   IsSaved = FALSE;
  518. }
  519.  
  520.  
  521.  
  522.  
  523. /*
  524.     DeletePlayers() allows deleting of players or marking them as withdrawn.
  525.     It uses the player selection functions.
  526. */
  527. void DeletePlayers(void)
  528.  
  529. {
  530.   /*
  531.       Check, if we really may delete players
  532.   */
  533.   if (NumRounds > 0  &&  RoundRobinTournament)
  534.   { ShowError((char *) GetChaosString(MSG_NO_PLAYER_DELETE));
  535.     return;
  536.   }
  537.   if (NumRounds > 0)
  538.   { if (!AskContinue((char *) GetChaosString(MSG_DELETE_PLAYER_REQUEST)))
  539.     { return;
  540.     }
  541.   }
  542.  
  543.   if (ProcessPlrSelWnd((char *) GetChaosString(WND_PLAYER_DELSEL_TITLE),
  544.                (char *) GetChaosString(BUTTON_DELETE_TITLE),
  545.                *(char *) GetChaosString(BUTTON_DELETE_SC),
  546.                TNFLAGSF_WITHDRAWN, &PlayerList))
  547.   { struct Player *plr, *next;
  548.  
  549.     for (plr = (struct Player *) PlayerList.lh_Head;
  550.      plr->Tn_Node.ln_Succ  !=  NULL;
  551.      plr = (struct Player *) plr->Tn_Node.ln_Succ)
  552.     { if (plr->Flags & TNFLAGSF_SELECTED)
  553.       { int Result;
  554.  
  555.     Result = (NumRounds == 0)  ?
  556.             AskExtContinue((char *)
  557.             GetChaosString(MSG_DELETE_THIS_PLAYER_REQUEST),
  558.                   (char *)
  559.             GetChaosString(BUTTONS_DELETE_THIS_PLAYER_REQUEST),
  560.             plr->Name)
  561.                    :
  562.             AskExtContinue((char *)
  563.             GetChaosString(MSG_THIS_PLAYER_GONE_REQUEST),
  564.                    (char *)
  565.             GetChaosString(BUTTONS_THIS_PLAYER_GONE_REQUEST),
  566.             plr->Name);
  567.  
  568.     switch(Result)
  569.     { case 1:   /*    "Delete him" or "Withdraw him" button   */
  570.         break;
  571.       case 2:   /*    "Skip him"                     button   */
  572.         plr->Flags &= ~TNFLAGSF_SELECTED;
  573.         break;
  574.       case 0:
  575.         return; /*    "Cancel"                       button   */
  576.     }
  577.       }
  578.     }
  579.  
  580.     /*
  581.     Note, that plr may be no longer valid after calling DeletePlayer()!
  582.     (That's why we use the next pointer.)
  583.     */
  584.     for (plr = (struct Player *) PlayerList.lh_Head;
  585.      (next = (struct Player *) plr->Tn_Node.ln_Succ)  !=  NULL;
  586.      plr = next)
  587.     { if (plr->Flags & TNFLAGSF_SELECTED)
  588.       { DeletePlayer(plr);
  589.       }
  590.     }
  591.   }
  592. }
  593.